home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / apps / gmemusage / gmemusage.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  14KB  |  634 lines

  1. /*
  2.  * gmemusage.c
  3.  *
  4.  * Reveal system memory usage
  5.  *
  6.  * Copyright 1994, Silicon Graphics, Inc.
  7.  * All Rights Reserved.
  8.  *
  9.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  10.  * the contents of this file may not be disclosed to third parties, copied or
  11.  * duplicated in any form, in whole or in part, without the prior written
  12.  * permission of Silicon Graphics, Inc.
  13.  *
  14.  * RESTRICTED RIGHTS LEGEND:
  15.  * Use, duplication or disclosure by the Government is subject to restrictions
  16.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  17.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  18.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  19.  * rights reserved under the Copyright Laws of the United States.
  20.  */
  21.  
  22. #include <sys/types.h>
  23. #include <sys/time.h>
  24. #include <sys/sysmp.h>
  25. #include <sys/wait.h>
  26.  
  27. #include <unistd.h>
  28. #include <stdio.h>
  29. #include <getopt.h>
  30. #include <string.h>
  31. #include <malloc.h>
  32. #include <stdlib.h>
  33. #include <bstring.h>
  34.  
  35. #include <gl/gl.h>
  36. #include <gl/device.h>
  37.  
  38. #include "process.h"
  39. #include "draw.h"
  40. #include "inode.h"
  41. #include "print.h"
  42.  
  43. #define DEF_THRESH 500
  44. #define DEF_DELTA 50
  45.  
  46. /*
  47.  * Set to 1 once the inode table has been initialized
  48.  */
  49. static int inodesInitted = 0;
  50.  
  51. /*
  52.  *  static void
  53.  *  PlaySound(char *sound)
  54.  *
  55.  *  Description:
  56.  *      run playaiff asynchronously to play a sound
  57.  *
  58.  *  Parameters:
  59.  *      sound
  60.  */
  61.  
  62. static void
  63. PlaySound(char *sound)
  64. {
  65.     static int firstTime = 1;
  66.     static int ok = 0;
  67.     static pid_t pid;
  68.     int fd, stat;
  69.  
  70.     if (firstTime) {
  71.     firstTime = 0;
  72.     if (sound) {
  73.         if (access("/usr/sbin/playaiff", F_OK | X_OK) == -1) {
  74.         perror("/usr/sbin/playiff");
  75.         return;
  76.         }
  77.  
  78.         if (access(sound, F_OK) == -1) {
  79.         perror(sound);
  80.         return;
  81.         }
  82.         ok = 1;
  83.     }
  84.     }
  85.  
  86.     if (!ok) {
  87.     return;
  88.     }
  89.  
  90.     /*
  91.      * Don't interrupt it if the last one is still playing
  92.      */
  93.     if (waitpid(pid, &stat, WNOHANG) == 0) {
  94.     return;
  95.     }
  96.  
  97.     if (pid = fork()) {
  98.     return;
  99.     }
  100.  
  101.     for (fd = getdtablesize(); fd > 2; fd--) {
  102.     close(fd);
  103.     }
  104.  
  105.     setuid(getuid());        /* avoid security problems */
  106.     execl("/usr/sbin/playaiff", "playaiff", sound, NULL);
  107.     exit(-1);
  108. }
  109.  
  110. /*
  111.  *  static void
  112.  *  InitInodes(void)
  113.  *
  114.  *  Description:
  115.  *      Make sure inodes are initted.  This gets called from two
  116.  *      different places, and the flag inodesInitted is global.
  117.  */
  118.  
  119. static void
  120. InitInodes(void)
  121. {
  122.     if (!inodesInitted) {
  123.     WaitMessage("Initializing inode lookup table...", NULL);
  124.     InodeInit();
  125.     inodesInitted = 1;
  126.     }    
  127. }
  128.  
  129. /*
  130.  *  char *
  131.  *  HandleMouse(PROGRAM *usage, long mousex, long mousey, int *procMode,
  132.  *              int dragging)
  133.  *
  134.  *  Description:
  135.  *      Handle mouse events.  We use the mouse to select bars to
  136.  *      display detailed breakdowns, and to leave detailed mode.  The
  137.  *      passed in procMode gets cleared if we should leave detailed
  138.  *      mode.
  139.  *
  140.  *  Parameters:
  141.  *      usage      current all programs usage being displayed
  142.  *      mousex     mouse horiz position
  143.  *      mousey     mouse vert position
  144.  *      procMode   pointer to variable that says whether we're already
  145.  *                 in procMode
  146.  *      dragging   1 if we're dragging
  147.  *
  148.  *  Returns:
  149.  *      pointer to name of program selected
  150.  */
  151.  
  152. char *
  153. HandleMouse(PROGRAM *usage, long mousex, long mousey, int *procMode,
  154.         int dragging)
  155. {
  156.     static char *oldProcName;
  157.     char *procName;
  158.     long originx, originy;
  159.  
  160.     getorigin(&originx, &originy);
  161.     mousex -= originx;
  162.     mousey -= originy;
  163.     
  164.     procName = Select(usage, mousex, mousey, procMode, dragging);
  165.  
  166.     if (!procName && *procMode) {
  167.     return oldProcName;
  168.     }
  169.  
  170.     if (procName) {
  171.     if (!inodesInitted && strcmp(procName, IRIX) != 0) {
  172.         if (dragging) {
  173.         unqdevice(MOUSEX);
  174.         unqdevice(MOUSEY);
  175.         }
  176.         InitInodes();
  177.         if (dragging) {
  178.         qdevice(MOUSEX);
  179.         qdevice(MOUSEY);
  180.         }
  181.     }
  182.     *procMode = 1;
  183.     if (oldProcName) {
  184.         free(oldProcName);
  185.     }
  186.     oldProcName = procName;
  187.     }
  188.  
  189.     return procName;
  190. }
  191.  
  192. int
  193. main(int argc, char *argv[])
  194. {
  195.     int glfd, opt, threshDelta = DEF_DELTA, doHelp = 0, doFreeze = 0;
  196.     int gotInput, doProcMode = 0, needNewColors = 0, inodesInitted = 0;
  197.     int barTotal, progBarTotal, numBars, numProgBars, dragging = 0;
  198.     int oldProgBarTotal, soundThresh = 12, pgsize;
  199.     fd_set fds, tfds;
  200.     PROGRAM *usage = NULL, *lastUsage = NULL;
  201.     PROGRAM *progUsage = NULL, *lastProgUsage = NULL;
  202.     long physMem, freeMem, threshHold = DEF_THRESH;
  203.     long dev, originx, originy;
  204.     short value, mousex, mousey;
  205.     struct timeval tv;
  206.     char *str, *procName = NULL, *newProcName = NULL;
  207.     PROGNAME *progNames = NULL, *name, *prev = NULL;
  208.     UsageType type, newType;
  209.     SecondType stype, newStype;
  210.     long usecTimeOut = 500000, secTimeOut = 0, msecTimeOut;
  211.     struct rminfo rminfo;
  212.     char *usageSound = getenv("USAGESOUND");
  213.  
  214.     if (geteuid() != 0) {
  215.     fprintf(stderr, "%s must be run as root or it must be setuid root.\n",
  216.         argv[0]);
  217.     exit(1);
  218.     }
  219.  
  220.     type = newType = Physical;
  221.     stype = newStype = None;
  222.     /*
  223.      * Process command line arguments
  224.      */
  225.     opterr = 0;
  226.     while ((opt = getopt(argc, argv, "a:g:i:d:mprst:u")) != EOF) {
  227.     switch (opt) {
  228.     case 'a':
  229.         usageSound = optarg;
  230.         break;
  231.     case 'g':
  232.         soundThresh = atoi(optarg);
  233.         break;
  234.     case 'i':
  235.         msecTimeOut = atoi(optarg);
  236.         secTimeOut = msecTimeOut / 1000;
  237.         usecTimeOut = 1000 * (msecTimeOut % 1000);
  238.         break;
  239.     case 'd':
  240.         threshDelta = atoi(optarg);
  241.         if (threshDelta <= 0) {
  242.         fprintf(stderr, "Resetting delta from %d\n", threshDelta);
  243.         threshDelta = DEF_DELTA;
  244.         }
  245.         break;
  246.     case 'm':
  247.         type = newType = MappedObjects;
  248.         break;
  249.     case 'p':
  250.         type = newType = Physical;
  251.         break;
  252.     case 'r':
  253.         type = newType = Resident;
  254.         break;
  255.     case 's':
  256.         type = newType = Size;
  257.         break;
  258.     case 't':
  259.         threshHold = atoi(optarg);
  260.         break;
  261.     case 'u':
  262.         InvalidateInodeTable();
  263.         break;
  264.     default:
  265.         doHelp = 1;
  266.     }
  267.     }
  268.  
  269.     while (optind < argc) {
  270.     name = malloc(sizeof *name);
  271.     name->name = argv[optind];
  272.     name->next = NULL;
  273.  
  274.     if (prev) {
  275.         prev->next = name;
  276.     } else {
  277.         progNames = name;
  278.     }
  279.     prev = name;
  280.     optind++;
  281.     }
  282.  
  283.     if (sysmp(MP_SAGET, MPSA_RMINFO, &rminfo, sizeof rminfo) == -1) {
  284.     perror("sysmp");
  285.     return 1;
  286.     }
  287.  
  288.     pgsize = getpagesize()/1024;
  289.  
  290.     physMem = rminfo.physmem * pgsize;
  291.  
  292.     foreground();
  293.     Init(progNames, threshHold);
  294.  
  295.     glfd = qgetfd();
  296.  
  297.     qdevice(ESCKEY);
  298.     qdevice(HKEY);
  299.     qdevice(MKEY);
  300.     qdevice(PKEY);
  301.     qdevice(RKEY);
  302.     qdevice(SKEY);
  303.     qdevice(TKEY);
  304.     qdevice(VKEY);
  305.     qdevice(UPARROWKEY);
  306.     qdevice(DOWNARROWKEY);
  307.     qdevice(SPACEKEY);
  308.     qdevice(WINFREEZE);
  309.     qdevice(WINTHAW);
  310.     qdevice(LEFTMOUSE);
  311.     tie(LEFTMOUSE, MOUSEX, MOUSEY);
  312.  
  313.     FD_ZERO(&fds);
  314.     FD_SET(glfd, &fds);
  315.  
  316.     tv.tv_sec = secTimeOut;
  317.     tv.tv_usec = usecTimeOut;
  318.  
  319.     gotInput = 0;
  320.  
  321.     if (type == MappedObjects) {
  322.     InitInodes();
  323.     }
  324.  
  325.     while (1) {
  326.     /*
  327.      * Draw the window, either help or the usage chart
  328.      */
  329.     if (!doFreeze) {
  330.         if (doHelp) {
  331.         Help();
  332.         } else {
  333.         /*
  334.          * If the user pressed a key that we can deal with without
  335.          * getting all our data again, just redraw.
  336.          */
  337.         if (!gotInput || type != newType || stype != newStype) {
  338.             stype = newStype;
  339.             type = newType;
  340.             if (lastUsage) {
  341.             FreeUsage(lastUsage);
  342.             }
  343.             lastUsage = usage;
  344.             if (lastProgUsage) {
  345.             FreeUsage(lastProgUsage);
  346.             }
  347.             lastProgUsage = progUsage;
  348.  
  349.             if (type == MappedObjects) {
  350.             GetObjInfo(doProcMode ? procName : NULL,
  351.                     &usage, &progUsage);
  352.             } else {
  353.             GetProcInfo(doProcMode ? procName : NULL,
  354.                     &usage, &progUsage);
  355.             }
  356.             
  357.             if (sysmp(MP_SAGET, MPSA_RMINFO, &rminfo,
  358.                   sizeof rminfo) == -1) {
  359.             perror("sysmp");
  360.             return 1;
  361.             }
  362.             freeMem = rminfo.freemem * pgsize;
  363.  
  364.             if (usage) {
  365.             usage = DrawSetup(usage,
  366.                       needNewColors ? NULL : lastUsage,
  367.                       physMem, freeMem, type, stype, 1,
  368.                       &barTotal, &numBars);
  369.             }
  370.             if (progUsage) {
  371.             progUsage = DrawSetup(progUsage,
  372.                           needNewColors ?
  373.                           NULL : lastProgUsage,
  374.                           physMem, freeMem,
  375.                           type, stype, 0, &progBarTotal,
  376.                           &numProgBars);
  377.             if (usageSound) {
  378.                 if (oldProgBarTotal == 0 ||
  379.                 oldProgBarTotal > progBarTotal) {
  380.                 oldProgBarTotal = progBarTotal;
  381.                 } else if (progBarTotal >
  382.                        oldProgBarTotal + soundThresh) {
  383.                 PlaySound(usageSound);
  384.                 oldProgBarTotal = progBarTotal;
  385.                 }
  386.             }
  387.             }
  388.             if (doProcMode && !progUsage) {
  389.             doProcMode = 0;
  390.             }
  391.             needNewColors = 0;
  392.         }
  393.         
  394.         if (doProcMode && progUsage) {
  395.             DrawShadow(usage, barTotal, procName);
  396.             Draw(progUsage, progBarTotal, numProgBars,
  397.              procName, type, stype);
  398.         } else if (usage) {
  399.             Draw(usage, barTotal, numBars, NULL, type, stype);
  400.         }
  401.         gotInput = 0;
  402.         }
  403.     }
  404.  
  405.     /*
  406.      * Wait for GL events, timing out after half a second
  407.      */
  408.     tfds = fds;
  409.     if (select(glfd + 1, &tfds, NULL, NULL,
  410.            (doHelp || doFreeze) ? NULL : &tv) < 0) {
  411.         perror("select");
  412.         return 1;
  413.     }
  414.  
  415.     /*
  416.      * Process GL events
  417.      */
  418.     if (FD_ISSET(glfd, &tfds)) {
  419.         while (qtest()) {
  420.         dev = qread(&value);
  421.         switch (dev) {
  422.         case HKEY:
  423.             /*
  424.              * Help
  425.              */
  426.             if (value == 0) {
  427.             doHelp = 1;
  428.             needNewColors = 1;
  429.             }
  430.             break;
  431.         case SPACEKEY:
  432.             /*
  433.              * End of help
  434.              */
  435.             if (value == 0) {
  436.             doProcMode = 0;
  437.             doHelp = 0;
  438.             }
  439.             break;
  440.         case MKEY:
  441.             if (value == 0) {
  442.             newStype = stype % Phys;
  443.             newType = MappedObjects;
  444.             doHelp = 0;
  445.             InitInodes();
  446.             needNewColors = 1;
  447.             }
  448.             break;
  449.         case PKEY:
  450.             /*
  451.              * Physical Memory Breakdown
  452.              */
  453.             if (value == 0) {
  454.             if (procName && strcmp(procName, IRIX) == 0) {
  455.                 newStype = None;
  456.             } else {
  457.                 newStype = stype % Phys;
  458.             }
  459.             newType = Physical;
  460.             doHelp = 0;
  461.             needNewColors = 1;
  462.             }
  463.             break;
  464.         case RKEY:
  465.             /*
  466.              * Resident Sizes of Processes
  467.              */
  468.             if (value == 0) {
  469.             if (!doProcMode
  470.                 || strcmp(procName, IRIX) != 0) {
  471.                 newStype = stype % Res;
  472.                 newType = Resident;
  473.                 doHelp = 0;
  474.                 needNewColors = 1;
  475.             }
  476.             }
  477.             break;
  478.         case SKEY:
  479.             /*
  480.              * Total Sizes of Processes
  481.              */
  482.             if (value == 0) {
  483.             if (!doProcMode
  484.                 || strcmp(procName, IRIX) != 0) {
  485.                 newStype = stype % (Res + 1);
  486.                 newType = Size;
  487.                 doHelp = 0;
  488.                 needNewColors = 1;
  489.             }
  490.             }
  491.             break;
  492.         case TKEY:
  493.             if (value == 0) {
  494.             if (doProcMode && progUsage) {
  495.                 PrintUsage(stdout, PRProc, progUsage, procName);
  496.             } else if (usage) {
  497.                 PrintUsage(stdout,
  498.                        type == MappedObjects ? PRMaps : PRAll,
  499.                        usage, NULL);
  500.             }
  501.             }
  502.             break;
  503.         case VKEY:
  504.             if (value == 0) {
  505.             doHelp = 0;
  506.             newStype = stype + 1;
  507.             switch (type) {
  508.             case Size:
  509.                 newStype %= Res + 1;
  510.                 break;
  511.             case Resident:
  512.                 newStype %= Res;
  513.                 break;
  514.             case Physical:
  515.                 if (procName && strcmp(procName, IRIX) == 0) {
  516.                 newStype = None;
  517.                 break;
  518.                 }
  519.                 /* intentional fall through */
  520.             case MappedObjects:
  521.                 newStype %= Phys;
  522.                 break;
  523.             default:
  524.                 newStype = None;
  525.                 break;
  526.             }
  527.             }
  528.             break;
  529.         case ESCKEY:
  530.             /*
  531.              * Exit
  532.              */
  533.             if (value == 0) {
  534.             exit(0);
  535.             }
  536.             break;
  537.         case REDRAW:
  538.             /*
  539.              * Resize event
  540.              */
  541.             gotInput = 1;
  542.             Resize();
  543.             break;
  544.         case UPARROWKEY:
  545.             /*
  546.              * Increase threshhold
  547.              */
  548.             if (value == 0) {
  549.             if (threshHold == 1)
  550.                 threshHold = 0;
  551.             threshHold += threshDelta;
  552.             SetThreshHold(threshHold);
  553.             doHelp = 0;
  554.             needNewColors = 1;
  555.             }
  556.             break;
  557.         case DOWNARROWKEY:
  558.             /*
  559.              * Decrease threshhold
  560.              */
  561.             if (value == 0) {
  562.             if (threshHold == threshDelta)
  563.                 threshHold = 1;
  564.             else
  565.                 threshHold -= threshDelta;
  566.             if (threshHold < 0) {
  567.                 threshHold = 0;
  568.             }
  569.             SetThreshHold(threshHold);
  570.             doHelp = 0;
  571.             needNewColors = 1;
  572.             }
  573.             break;
  574.         case MOUSEX:
  575.             needNewColors = 1;
  576.             mousex = value;
  577.             procName = HandleMouse(usage, mousex, mousey,
  578.                        &doProcMode, 1);
  579.             oldProgBarTotal = 0;
  580.             break;
  581.         case MOUSEY:
  582.             needNewColors = 1;
  583.             mousey = value;
  584.             procName = HandleMouse(usage, mousex, mousey,
  585.                        &doProcMode, 1);
  586.             oldProgBarTotal = 0;
  587.             break;
  588.         case LEFTMOUSE:
  589.             needNewColors = 1;
  590.             (void)qread(&mousex);
  591.             (void)qread(&mousey);
  592.             if (usage && !doHelp && value) {
  593.             /*
  594.              * This extra flag prevents switching bars if
  595.              * the user is moving the mouse at the same
  596.              * time that a bar is selected; if we start
  597.              * queueing mouse motion right away, we'll
  598.              * shift bars because off the vertical offset
  599.              * of the shadow chart.
  600.              */
  601.             int prevDoProcMode = doProcMode;
  602.             procName = HandleMouse(usage, mousex, mousey,
  603.                            &doProcMode, dragging);
  604.             oldProgBarTotal = 0;
  605.             if (procName && strcmp(procName, IRIX) == 0) {
  606.                 newStype = None;
  607.             }
  608.             if (prevDoProcMode && !dragging) {
  609.                 qdevice(MOUSEX);
  610.                 qdevice(MOUSEY);
  611.                 dragging = 1;
  612.             }
  613.             }
  614.             if (!value && dragging) {
  615.             unqdevice(MOUSEX);
  616.             unqdevice(MOUSEY);
  617.             dragging = 0;
  618.             }
  619.             break;
  620.         case WINFREEZE:
  621.             doFreeze = 1;
  622.             break;
  623.         case WINTHAW:
  624.             doFreeze = 0;
  625.             break;
  626.         default:
  627.             break;
  628.         }
  629.         }
  630.     }
  631.     }
  632.     return 0;
  633. }
  634.